package com.linkgie.galaxyframework.utils.runtime;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.Enumeration;
import java.util.Map;
import java.util.jar.Manifest;

import com.linkgie.galaxyframework.utils.CollectionUtils;

/**
 * 运行时工具类；
 * 
 * @author huanghaiquan
 *
 */
public class RuntimeUtils {

	private static final String JAVA_MAIN_CLASS_KEY_PREFIX = "JAVA_MAIN_CLASS";

//	private static String MAIN_CLASS;

//	static {
//		deduceMainClassFromEnvironment();
//	}

	/**
	 * 从上下文环境变量中查找入口类；
	 * <p>
	 * 
	 * 
	 * @return
	 */
	public static String deduceMainClassFromEnvironment() {
		String mainClass = null;
		@SuppressWarnings("unused")
		String processId;
		Map<String, String> env = System.getenv();
		for (String key : env.keySet()) {
			if (key.startsWith(JAVA_MAIN_CLASS_KEY_PREFIX)) {
				mainClass = env.get(key);
				String pidSection = key.substring(JAVA_MAIN_CLASS_KEY_PREFIX.length());
				if (pidSection.length() > 1 && pidSection.startsWith("_")) {
					processId = pidSection.substring(1);
				}
				break;
			}
		}

		return mainClass;
	}

	/**
	 * 从入口堆栈中查找入口类；
	 * <p>
	 * 
	 * 只有在执行 main 入口方法的入口线程中调用才能够返回正确的结果；
	 * 
	 * @return
	 */
	public static String deduceMainClassFromEntryStacktrace() {
		StackTraceElement[] stacktraces = new RuntimeException().getStackTrace();
		// 翻转堆栈，从最远调用开始查找，优化查找效率；
		CollectionUtils.reverse(stacktraces);
		for (StackTraceElement stktrc : stacktraces) {
			if ("main".equals(stktrc.getMethodName())) {
				String mainClassName = stktrc.getClassName();
				try {
					Class<?> mainClass = Class.forName(mainClassName);
					Method mainMethod = mainClass.getMethod("main", String[].class);
					if (Modifier.isStatic(mainMethod.getModifiers())) {
						return mainClassName;
					}
				} catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) {
				}
			}
		}

		return null;
	}

	// 由于此方法并不能可靠地返回预期的结果，因此注释掉此方法，避免引起误用；
//	/**
//	 * 返回当前运行进程的启动入口类；
//	 * <p>
//	 * 
//	 * 此方法解析返回环境参数 JAVA_MAIN_CLASS 环境变量的值；
//	 * 
//	 * @return
//	 */
//	public static String getProcessId() {
//		return processId;
//	}

	/**
	 * 返回 META-INF/MANIFEST.MF 中指定的启动类（即定义 main 方法的类型）；
	 * 
	 * @param classLoader 查找 META-INF/MANIFEST.MF 资源的类加载器；
	 * @return
	 */
	public static String deduceMainClassFromManifest(ClassLoader classLoader) {
		try {
			return getStartClass(classLoader.getResources("META-INF/MANIFEST.MF"));
		} catch (Exception ex) {
			return null;
		}
	}

	private static String getStartClass(Enumeration<URL> manifestResources) {
		while (manifestResources.hasMoreElements()) {
			try (InputStream inputStream = manifestResources.nextElement().openStream()) {
				Manifest manifest = new Manifest(inputStream);
				String startClass = manifest.getMainAttributes().getValue("Start-Class");
				if (startClass != null) {
					return startClass;
//					return Class.forName(startClass);
				}
			} catch (Exception ex) {
			}
		}
		return null;
	}
}
